home *** CD-ROM | disk | FTP | other *** search
-
- ;write error message
-
- chart_error:
- call error_exit ;write title
- db 17,'Current box must not be parent box to subchart',0
-
- ;write error message
-
- open_error:
- call error_exit ;write title
- db 33,'Cant open file',0
-
- ;load flowchart from disk
-
- load_chart:
- cmp b new_chart,0ffh ;is there a chart in memory?
- je load ;load chart if not
- mov ax,w current_box ;load id of current box
- call get_box ;get its pointer
- es cmp w[di+child],0 ;is it the parent of a subchart?
- je load ;check if flowchart saved if not
-
- ;exit with error
-
- call chart_error ;write error message
- clc ;indicate ok otherwise
- ret ;exit
- merge_chart:
- mov w current_box,bp ;store current box
- call load ;load chart
- mov bp,w current_box ;load current box
- or bp,bp ;reset chart?
- if ne stc ;exit to start of chart loop if not
- ret ;exit
-
- ;check if existing flowchart has been saved
-
- load:
- call tail ;check if flowchart has been saved
- jc ret ;exit if error
- call get_available_memory ;get memory available
- cmc ;complement carry
- jnc ret ;exit if overflow
- or ax,dx ;is there any memory available?
- je ret ;exit if not
- call filename_prompt ;write prompt to bottom line
-
- ;get filename from user
-
- call get_string ;get filename
- dw filename ;offset to string buffer
- db 64,1 ;maximum string size
- jnc >a1 ;open file for reading if ok
- clc ;indicate escape pressed
- ret ;exit
-
- ;open new chart file for reading
-
- a1:
- mov dx,si ;load offset to filename
- load_chart_dx:
- mov ax,03d00h ;load function parameter
- int 021h ;create file
- jnc >a1 ;subtract base if file opened
- call open_error ;write error
- clc ;indicate ok otherwise
- ret ;exit
-
- ;save current box and next new box markers
-
- a1:
- mov bx,ax ;save handle
- mov w handle,ax
- mov ah,03fh ;load function parameter
- mov cx,4 ;load count
- mov dx,o temp4 ;incase chart already loaded
- int 021h ;read current box and new box from disk
- if c jmp exit_read ;exit if error
-
- ;if no existing chart then initialise box markers
-
- mov cx,w next_box ;load number of first new box
- mov ax,w temp4 ;load current box of new chart
- mov dx,first_box ;initialise next vacant box marker
- jcxz >a1 ;store current box if not
- mov ax,w current_box ;don't change current box
- mov dx,cx ;load next (old) vacant box
-
- ;get pointer to start of new box records
-
- a1:
- mov w temp5,ax ;store current box
- mov w next_box,dx
- mov ax,w temp4+2 ;calculate number of boxes
- sub ax,first_box
- mov bx,box_record ;load size of each box
- mul bx ;calculate size of boxes block
- mov w temp3,ax ;save it
- mov w temp3+2,dx
-
- ;move existing descripter data up by size of new block
-
- les ax,w start_free_memory ;load pointer to start of free memory
- mov dx,es
- mov w shift_count,ax ;save it
- mov w shift_count+2,dx
- call get_pointer ;calculate pointer
- mov si,di ;copy it as source pointer
-
- ;calculate pointer to start of descripter data new address
-
- add ax,w temp3 ;calculate address to end of new block
- adc dx,w temp3+2
- push es ;save source segment
- call get_pointer ;calculate pointer
-
- ;calculate size of block
-
- mov ax,w next_box ;calculate address to start of text
- call get_box_address ;get pointer to box
- sub w shift_count,ax ;calculate size of text data
- sbb w shift_count+2,dx
-
- ;save size of existing descripter block
-
- mov ax,w shift_count ;copy size of block
- mov w temp2,ax
- mov ax,w shift_count+2
- mov w temp2+2,ax
- pull ds ;load source segment
- call shift_up ;shift descripter data up
-
- ;update pointers to existing descipters
-
- mov ds,ax,cs ;restore data segment register
- mov cx,w next_box ;load last existing box id
- les ax,w chart ;load pointer to start of existing chart
- mov dx,es
- call get_pointer ;calculate pointer
- mov bx,w temp3 ;load size of new boxes block
- mov dx,w temp3+2
- call chart_addresses2 ;update pointers
-
- ;read new box data to end of existing box data
-
- mov ax,w temp3 ;copy size of block
- mov w shift_count,ax
- mov ax,w temp3+2
- mov w shift_count+2,ax
- mov ax,w next_box ;calculate pointer to start of new block
- call get_box_address ;get pointer to box
- call read_block ;read box data from disk
- jc >e1 ;abort chart if error
-
- ;read remaining new data to end of old descripter data
-
- mov ax,w start_free_memory ;load address to end of data
- mov dx,w start_free_memory+2
- mov w shift_count+2,-1 ;read to end of file
- call read_block ;read descripter text data from disk
- jnc >a1 ;link chart if loaded ok
- e1:
- mov w current_box,0 ;indicate error and clear chart
- ret ;exit
-
- ;link new chart to existing chart
-
- a1:
- mov ax,w current_box ;load current box
- call get_box ;get pointer to it
- mov ax,w next_box ;load id of first box in new chart
- es mov w[di+child],ax ;link charts
-
- ;update parent pointers for current box
-
- mov bp,ax ;calculate number of existing boxes
- sub bp,first_box
- call get_box_address ;get pointer to box
- call get_pointer ;calculate pointer
- add w temp2,ax ;calculate offset to start of new
- adc w temp2+2,dx ;descripter strings
-
- ;calculate number of new boxes
-
- mov cx,w temp4+2 ;calculate number of new boxes
- sub cx,first_box
- add w next_box,cx ;add new boxes to existing boxes
- mov ds,ax,es ;copy pointer to boxes
- mov si,di
-
- ;check basic route slots
-
- b1:
- mov bx,previous ;load offset to 'previous' route slot
- call update_slot ;check if slot points to another box
- mov bx,yes ;check yes route slot
- call update_slot ;check if slot points to another box
- mov bx,no ;check no route slot
- call update_slot ;check if slot points to another box
-
- ;if parent route is vacant, point it to current box of existing chart
-
- mov bx,parent ;load offset to 'parent' route slot
- cmp w[si+bx],0 ;is box on top level of new chart?
- mov ax,bp ;assume it isn't
- if e cs mov ax,w current_box ;point it to current box if it is
- add w[si+bx],ax ;update child route slot
-
- ;update child route and pointer to descripter
-
- mov bx,child ;load offset to 'child' route slot
- call update_slot ;check if slot points to another box
- mov bx,descripter ;load offest to descripter pointer
- cs mov ax,w temp2 ;load base address for desripter
- add w[si+bx],ax ;add it to offset
- cs mov ax,w temp2+2
- adc w[si+bx+2],ax
-
- ;move to next box record
-
- cmp si,0fc00h ;is there reasonable room above
- jb >a1 ;update numbers if there is
- sub si,08000h ;normalise pointer
- mov ax,ds
- add ax,0800h
- mov ds,ax
- a1:
- add si,box_record ;move to next record
- loop b1 ;decrement loop count
-
- ;update current box
-
- mov ds,ax,cs ;copy segment to workspace
- mov ax,w temp5 ;copy current box
- mov w current_box,ax
-
- ;reset chart variables
-
- xor ax,ax ;clear register
- mov b chart_flag,4 ;set chart entry flag
- mov b box_made,0ffh ;dont create a box
- mov b new_chart,080h ;indicate chart loaded
- mov w key_option,ax ;clear key option flag
- mov w box_save,ax ;clear flag/box store
- mov w insert_mode,ax ;clear flag
- mov w link_box,ax ;clear link box
- mov w box_to_subchart,ax ;clear flag
- mov w subchart_link,ax ;clear subchart follow box
- mov w sub_stack,top_stack ;clear stack
- mov b message,al ;clear message buffer
-
- ;close file and exit
-
- call chart_bookmarks ;copy any bookmarks to table
- call close_input_file ;close file
- clc ;indicate all ok
- ret ;exit
-
- ;update box slot
-
- update_slot:
- cmp w[si+bx],first_box ;does slot route point to another box?
- if ae add w[si+bx],bp ;update it if it does
- ret ;exit
-
- ;convert segment:offset (ax:si) to 20 bit address
-
- ptr_addr:
- xor dx,dx ;clear high order nibble of source addr
- shl ax,1 ;store high order nibble of segment
- rcl dl,1 ;value into al
- shl ax,1
- rcl dl,1
- shl ax,1
- rcl dl,1
- shl ax,1
- rcl dl,1
- add ax,si ;calculate low word of address
- adc dl,dh ;add carry to high order nibble
- ret ;return
-
- ;exit with error
-
- e1:
- call close_input_file ;close file
- memory_error:
- call error_exit ;exit with error
- db 30,'insufficient memory',0
-
- ;calculate memory available
-
- get_available_memory:
- mov ax,w ram_top ;load address to end of free memory
- mov dx,w ram_top+2
- sub ax,w start_free_memory ;subtract base of free memory
- sbb dx,w start_free_memory+2
- ret ;exit
-
- ;read data from disk
- ;calculate memory available
-
- read_block:
- mov w temp1,ax ;save address to start of block
- mov w temp1+2,dx
- b1:
- mov ax,w temp1 ;load address to start of block
- mov dx,w temp1+2
- call get_pointer ;convert address to pointer
-
- ;range check pointer
-
- call load_count ;load byte count
- call get_available_memory ;get memory available
- or dx,dx ;is there enough memory?
- jne >a1 ;load block if there is
- cmp ax,cx ;is there enough memory?
- if be mov cx,ax ;load block if there is
- or ax,ax ;is there any available memory?
- je e1 ;exit if not
-
- ;range check pointer
-
- a1:
- call range_check_dptr ;range check pointer
- mov dx,di ;load offset
- mov ax,es ;copy segment
- mov bx,w handle ;load handle
- mov ds,ax
- mov ah,03fh ;load function parameter
- int 021h ;read block from disk
- mov ds,di,cs ;restore data segment register
- jnc >a1 ;check if all bytes were read if ok
-
- ;close file and exit with error message
-
- exit_read:
- call close_input_file ;close file
- call error_exit ;exit with error
- db 30,'Cant read from disk',0
-
- ;check if any bytes were read
-
- a1:
- add w start_free_memory,ax ;add bytes read to address
- adc w start_free_memory+2,0
- add w temp1,ax ;add to offset to start of last block
- adc w temp1+2,0
- or ax,ax ;were any bytes read?
- jne b1 ;read next block if there were
- ret ;exit
-
- ;close input file
-
- close_input_file:
- mov ah,03eh ;load function paramter
- cs mov bx,w handle ;load input handle
- int 021h ;close file
- ret ;exit
-
- ;goto dos shell
-
- dos_shell:
- call cls ;clear the screen
- call writexy ;write message
- db 14,21
- db 'Please enter amount of memory to reserve for Chart.',0
- call writexy
- db 26,22
- db 'Minimum required ',0
-
- ;calculate minimum bytes required
-
- mov ax,cs ;load code segment
- mov bx,16 ;multiply it by 16
- mul bx
- mov bx,w start_free_memory ;load top of memory address
- mov cx,w start_free_memory+2
- sub bx,ax ;calculate minimum bytes needed
- sbb cx,dx
- add bx,02010h ;add 8k bytes needed for stacks
- adc cx,0
- mov ax,bx ;convert number to string
- mov dx,cx
- mov w reserve,ax ;save it
- mov w reserve+2,dx
-
- ;write bytes required to screen
-
- mov di,o s ;load offset to buffer
- call store_number3 ;convert required bytes to string
- mov cx,di ;calculate size of string
- mov di,o left_route ;load destination buffer offset
- sub cx,o s
- a1:
- std ;read backwards
- lodsb ;load character from string
- cld ;write forwards
- stosb
- call write_chr ;write it to screen
- loop a1 ;decrement loop count
- xor al,al ;terminate string
- stosb
- call write ;write bytes message
- db ' bytes.',0
-
- ;get minimum bytes required from user
-
- call get_string ;get bytes required
- dw left_route
- db 7,1
- if c jmp body ;exit to menu if escape pressed
-
- ;convert ascii digits to binary
-
- call get_val ;convert string to number
- jc >a2 ;prompt again if error
- cmp dx,w reserve+2 ;is amount too small?
- ja >a1 ;reserve bytes if not
- jb >a2 ;reprompt if it is
- cmp ax,w reserve ;is amount too small?
- jae >a1 ;reserve bytes if not
- a2:
- jmp dos_shell ;reprompt if it is
-
- ;save program size
-
- a1:
- mov bx,ax ;save bytes to reserve
- mov cx,dx
- mov ax,cs ;calculate address to start of program
- xor si,si
- call ptr_addr ;convert pointer to address
- add ax,bx ;add size of program
- adc dx,cx
- sub ax,32 ;allow for paragraph overlap
- sbb dx,0
- mov w ram_top,ax ;mark end of program
- mov w ram_top+2,dx
-
- ;resize program and data
-
- shr cx,1 ;convert 20 bit address to segment
- rcr bx,1
- shr cx,1
- rcr bx,1
- shr cx,1
- rcr bx,1
- shr cx,1
- rcr bx,1
-
- ;resize program
-
- mov w end_stack,bx ;save it
- add bx,010h ;add a paragraph
- mov es,ax,cs ;copy base segment
- mov ah,04ah ;load function parameter
- int 021h ;resize memory allocation
-
- ;write exit message
-
- call writexy ;write prompt
- db 1,11
- db 'Type EXIT to return to Chart',0
-
- ;get comspec filename
-
- mov es,w[02ch] ;load segment to environment block
- xor di,di ;load offset
- xor al,al
- a1:
- mov si,o comspec_string ;load offset to comspec search string
- mov cx,8 ;load length of string
- repe
- cmpsb ;compare strings
- je >a2 ;load offset to comspec if found
-
- ;move to next entry
-
- mov cx,08000h ;load maximum environment block size
- repne
- scasb ;scan to end of environment string
- es cmp b[di],0 ;end of environment block?
- jne a1 ;check next environment string if not
-
- ;write error message
-
- call writexy ;write can't load comspec message
- db 1,13
- db 'Cannot find COMSPEC, press ESC',0
- a4:
- call key ;fetch keypress
- cs mov b middle_5,0 ;cancel quick exit flag
- jc a4 ;get another keypress if middle 5 down
- jne a4 ;fetch another keypress if not escape
- jmp long >b1 ;resize program block
-
- ;initialise parameter block for exec function
-
- a2:
- call restore_cursor ;restore cursor type
- mov dx,di ;load offset to comspec filename
- mov es,bx,cs ;load code segment
-
- ;initialise file control blocks
-
- mov di,o s ;load offset to fcb #1
- mov si,o fcb ;load offset to fcb string
- mov ax,02901 ;load function parameters
- int 021h ;format fcb #1
- mov ds,ax,cs ;restore segment register
- mov di,o s+010h ;load offset to fcb #2
- mov si,o fcb ;load offset to fcb string
- mov ax,02901 ;load function parameters
- int 021h ;format fcb #2
-
- ;point keyboard interrupt to interrupt handler
-
- push dx ;save offset to comspec
- mov ax,03509h ;load function parameter and interrupt
- int 021h ;get interrupt handler
- mov ds,ax,cs ;restore segment register
- mov w interrupt_exit,bx ;save offset
- mov w interrupt_exit+2,es ;save segment
- mov ax,02509h ;load parameter and interrupt number
- mov dx,o interrupt_entry ;load offset to interrupt handler
- int 021h ;point interrupt
-
- ;initialise parameter block
-
- mov w >e5,cs ;store segment address of program
- mov w >e5+4,cs
- mov w >e5+8,cs
-
- ;set up temporary stack
-
- pull dx ;restore offset to comspec
- mov es,ax,cs ;load code segment
- mov bx,o >e3 ;load offset
- add ax,w end_stack ;add program size
- sub ax,01010h ;subtract a segment
- cli ;disable interrupts
- mov sp,-2 ;load offset to temporary stack
- mov ss,ax ;load segment to temporary stack
- sub ax,0100h ;calculate box stack segment
- mov w stack_segment,ax ;store it
-
- ;call comspec
-
- mov b chart_active,0 ;indicate chart in dos shell
- mov b direct_video,-1 ;don't write through bios
- mov ds,w[02ch] ;load segment to comspec filename
- mov ax,04b00h ;load function parameters
- sti ;enable interrupts
- int 021h ;call comspec
- mov ds,ax,cs ;restore segment registers
- mov es,ax
- mov b chart_active,0ffh ;indicate chart in op
- jnc >b2 ;exit if ok
-
- ;write error message
-
- call writexy ;write can't load comspec message
- db 1,13
- db 'Cannot load COMSPEC, press ESC',0
- a4:
- call key ;fetch keypress
- cs mov b middle_5,0 ;cancel quick exit flag
- jc a4 ;get another keypress if middle 5 down
- jne a4 ;fetch another keypress if not escape
-
- ;point keyboard interrupt to interrupt handler
-
- b2:
- mov ax,02509h ;load parameter and interrupt number
- cs lds dx,w interrupt_exit ;load offset to old interrupt handler
- int 021h ;restore interrupt
- mov ds,ax,cs ;restore data segment register
- sti ;enable interrupts
-
- ;check if enough memory to continue
-
- b1:
- call init_screen ;set screen mode
- mov bx,w[2] ;load ram top
- mov ax,cs ;load code segment
- sub bx,ax ;calculate original block size
- push bx ;save block
- mov es,ax ;load base segment
- mov ah,04ah ;load function parameter
- int 021h ;resize allocated memory
- jnc >b1 ;restore stack pointer if ok
-
- ;set stack pointer as it was when comspec was called
-
- pull ax ;clear old block from stack
- push bx ;save maximum paragraphs free
- mov ah,04ah ;load parameter
- int 021h ;get maximum bytes
- b1:
- pull ax ;load block size allocated
- mov bx,cs ;load base segment
- add ax,bx ;calculate stack segment
- sub ax,01000h
- mov ss,ax
- mov bx,ax ;copy segment
- sub bx,0100h ;calculate box stack segment
- mov w stack_segment,bx
- mov sp,-2
-
- ;restore ram top
-
- xor si,si ;convert stack pointer to address
- call ptr_addr
- mov w ram_top,ax ;save it
- mov w ram_top+2,dx
- jmp main ;join main loop
-
- ;exec funtion parameter block
-
- comspec_string db 'COMSPEC=',0 ;dos shell comspec string in environment
- ;block
-
- e3 dw 0 ;segment address of environment block
- dw >e4 ;offset of command tail
- e5 dw ? ;segment of command tail
- dw offset s ;segment:offset of fcb #1
- dw ?
- dw offset s+010h ;segment:offset of fcb #2
- dw ?
-
- e4 db 0 ;command tail passed to dos shell
- fcb db 13
-
- interrupt_exit dw 2 dup ? ;exit address for interrupt
-
- ;check if keypress is middle 5 of keypad (with num-lock off)
-
- b1:
- stc ;indicate key not down
- ret ;exit
- check_mid_5:
- in al,060h ;get key scan code
- cmp al,04ch ;is it middle 5 in keypad?
- jne b1 ;exit if not
- xor ax,ax ;load base segment
- mov ds,ax
- test b[0417],020h ;is num lock on?
- jne b1 ;exit if it is
-
- ;send acknowledge signal
-
- in al,61h ;read 8255 port pb
- or al,80h ;set ack signal
- out 61h,al ;send ack signal
- and al,7fh ;reset keyb ack
- out 61h,al ;and 8255 port pb
- mov al,20h ;notify int cntrllr
- out 20h,al
- clc ;indicate key pressed
- ret ;exit
-
- ;exit from handler
-
- b2:
- pull ds,ax ;restore registers
- b1:
- cs jmp d[interrupt_exit] ;exit
-
- ;keyboard interrupt handler
-
- interrupt_entry:
- cs cmp b chart_active,080h ;is chart in dos shell?
- ja b1 ;exit if not
- push ax,ds ;save registers
- jb >a1 ;check keypress if first call from shell
- call check_mid_5 ;check if middle 5 of key pad pressed
- jc b2 ;exit if not down
- cs mov b middle_5,0ffh ;indicate middle 5 is down
- jmp b2 ;exit
-
- ;check if foreground process is msdos
-
- a1:
- call check_mid_5 ;check if middle 5 of key pad pressed
- jc b2 ;exit if not down
- push bx,cx,dx,si,di,bp,es ;save remainder of registers
- mov ax,w[0463h] ;load current crtc port address
- cs xchg w crtc_address,ax ;swap with secondary address
- push ax ;save port address to chart display
- mov ds,ax,cs ;copy code segment
- mov es,ax
- sti ;enable interrupts
- mov b chart_active,080h ;indicate chart in op
-
- ;get pointers to video map
-
- call get_screen ;get screen pointer
- mov w display_match,ax ;save screen types
- mov w cursor_data,dx ;save cursor coordinates
- mov w cursor_type,cx ;save cursor type
- call clear_cursor ;clear cursor from user screen
- pull ax ;load port address of chart display
- xchg w crtc_address,ax ;restore crtc address for chart display
- push ax ;save port address to current display
-
- ;check if current display mode will be overwritten
-
- xor dx,dx ;move pointer to start of video map
- call cursor ;position cursor
- mov ax,w display_match ;load both display types
- cmp al,ah ;are we overwriting the calling screen?
- je >a2 ;save screen if yes
- cmp b middle_5,0 ;did chart last exit from editor?
- jne >a1 ;set up stack if not
-
- ;backup video
-
- a2:
- lds si,w video_pointer ;load pointer to start of map
- cs mov w saved_screen,si ;save it
- cs mov w saved_screen+2,ds
- mov di,o video_backup ;load pointer to backup
- mov cx,2000 ;load size of screen map in words
- rep
- movsw ;backup screen
-
- ;set up stack
-
- a1:
- mov bx,sp ;save state of stack
- mov cx,ss
- mov ds,ax,cs ;copy code segment
- add ax,w end_stack ;add program size
- sub ax,01010h ;subtract a segment
- cli ;disable interrupts
- mov sp,-2 ;load offset to temporary stack
- mov ss,ax ;load segment to temporary stack
-
- ;save pointer to video map data
-
- push bx,cx ;save pointer
- sti ;re-enable interrupts
- mov w sub_stack,top_stack ;clear stack
- sub ax,0100h ;allow 4k for stack
- mov w stack_segment,ax
-
- ;call chart
-
- xor al,al ;load zero
- xchg b middle_5,al ;indicate calling menu level
- mov bp,w current_box ;load current box
- or al,al ;was middle 5 down
- je >a1 ;call main menu if not
-
- ;call editing level
-
- call clear_cursor ;clear cursor from user screen
- call flowchart ;call at editor level if it was
- jc >a2 ;exit if middle 5 pressed
- a1:
- call body ;call menu level
-
- ;restore stack
-
- a2:
- mov ds,ax,cs ;copy segment to workspace
- pull dx,ax ;restore stack pointer
- cli ;disable interrupts
- mov sp,ax ;restore offset to calling stack
- mov ss,dx ;restore segment to calling stack
- sti ;re-enable interrupts
-
- ;if display was overwritten the restore it's original state
-
- mov ax,w display_match ;load screen types
- cmp al,ah ;are we overwriting the calling screen?
- je >a2 ;save screen if yes
- cmp b middle_5,0 ;restore user screen?
- jne >a1 ;exit if not
-
- ;restore screen display map
-
- a2:
- les di,w saved_screen ;load pointer to map
- mov si,o video_backup ;load pointer to backup map
- mov cx,2000 ;load size of map
- rep
- movsw ;restore video
-
- ;restore cursor state and position
-
- a1:
- xor ax,ax ;load zero
- mov es,ax
- es mov al,b[0462h] ;load video page
- mov b active_page,al ;store page
- call clear_cursor ;clear cursor from user screen
- pull ax ;load port address of chart display
- xchg w crtc_address,ax ;restore crtc address for chart display
- push ax ;save port address to current display
-
- ;restore cursor state and position
-
- mov cx,w cursor_type ;save cursor type
- call set_cursor ;clear cursor from user screen
- mov dx,w cursor_data ;save cursor coordinates
- call cursor ;position cursor
- pull w crtc_address ;restore crtc address for chart display
- mov b chart_active,0 ;indicate chart not in op
- pull es,bp,di,si,dx,cx,bx,ds,ax ;restore registers
- iret ;exit
-
- ;check if safe to call BIOS
-
- int10:
- cs cmp b chart_active,080h ;is chart in dos shell?
- if ne int 010h ;call BIOS if not
- ret ;exit
-
- ;end